import {WL_CoreInterface, WL_ExtEventID} from "@/core/weila_datas";
import {WL} from "@/proto/weilapb";
import {Weila_MemDB} from "@/mem_store/weila_db";
import {
	WL_IDbService, WL_IDbServiceSession,
	WL_IDbServiceSessionInfo, WL_IDbServiceStaff,
	WL_IDbSession, WL_IDbSessionStatus, WL_IDbSessionType,
	WL_IDbUserInfo,
	WL_ServiceStatus
} from "@/proto/weilapb_external_data";
import {convertFromServiceSessionRaw, convertFromStaffRaws} from "@/proto/weilapb_utils";
import Long from "long";
import {WeilaPbBusinessWrapper} from "@/proto/weilapb_business_wrapper";
import debug from "debug";

const BLog = debug("BusinessLog");

export default class WLBusinessModule {
	constructor(private coreInterface: WL_CoreInterface) {
		this.coreInterface.registerPbMsgHandler(WL.Service.ServiceID.SERVICE_BUSINESS, this.onPbMsgHandler.bind(this));
	}

	private onPbMsgHandler(data: any): void {
		const serverMessage = data as WL.Service.IServiceMessage;
		const serviceHead = serverMessage.serviceHead;
		if (serviceHead!.commandType == WL.Service.CommandType.COMMAND_RESPONSE) {
			switch (serviceHead!.commandId) {
				case WL.Business.BusinessCommandId.BUSINESS_COMMAND_COMMON_GET_SESSION: {
					this.coreInterface.rspPbMsg(serviceHead!.seq!, serviceHead!.resultCode!,
						serviceHead!.resultCode == 0 ? serverMessage.businessMessage!.rspCommonGetSessions : null);
				}
				break;

				case WL.Business.BusinessCommandId.BUSINESS_COMMAND_COMMON_GET_STAFF_INVITE: {
					this.coreInterface.rspPbMsg(serviceHead!.seq!, serviceHead!.resultCode!,
						serviceHead!.resultCode == 0 ? serverMessage!.businessMessage!.rspCommonGetStaffInvite : null);
				}
				break;

				case WL.Business.BusinessCommandId.BUSINESS_COMMAND_CUSTOMER_CLOSE_SESSION: {
					this.coreInterface.rspPbMsg(serviceHead!.seq!, serviceHead!.resultCode!,
						serviceHead!.resultCode == 0 ? serverMessage!.businessMessage!.rspCustomerCloseSession : null);
				}
				break;
			}
		}else if (serviceHead!.commandType == WL.Service.CommandType.COMMAND_NOTIFY) {
			switch (serviceHead!.commandId) {
				case WL.Business.BusinessCommandId.BUSINESS_COMMAND_COMMON_SESSION_CHANGE: {
					const ntf = serverMessage!.businessMessage!.ntfCommonSessionChange;
					const serviceSessionInfo = convertFromServiceSessionRaw(ntf!.session!);
					this.coreInterface.sendExtEvent(WL_ExtEventID.WL_EXT_COMMON_SESSION_CHANGE_IND, serviceSessionInfo);

					if (serviceSessionInfo.serviceSession.serviceStatus == WL_ServiceStatus.SERVICE_STATUS_INIT) {
						(async () => {
							Weila_MemDB.getInstance().putService(serviceSessionInfo.service);
							convertFromStaffRaws(ntf!.session!.staffAttributes!).forEach(value => {
								Weila_MemDB.getInstance().putStaff(value);
							})

							Weila_MemDB.getInstance().putUsers(serviceSessionInfo.staffs.map(value => {
								return value.userData;
							}));

							Weila_MemDB.getInstance().putUser(serviceSessionInfo.customer!);
						})();
					}
				}
				break;
			}
		}
	}

	public async getSessionServiceFromServer(sessionId: string): Promise<WL_IDbServiceSessionInfo|undefined> {
		const buildMsgRet = WeilaPbBusinessWrapper.buildCommonGetSessionsReq([Long.fromValue(sessionId)]);
		if (buildMsgRet.resultCode == 0) {
			let dbUserInfos = [] as WL_IDbUserInfo[];
			try {
				const rsp = await this.coreInterface.sendPbMsg(buildMsgRet) as WL.Business.IRspCommonGetSessions;
				if (rsp.sessions!.length) {
					const serviceSessionInfo = convertFromServiceSessionRaw(rsp!.sessions![0]);
					dbUserInfos.push(...serviceSessionInfo.staffs.map(value => {
						return value.userData;
					}));
					dbUserInfos.push(serviceSessionInfo!.customer!);
					Weila_MemDB.getInstance().putUsers(dbUserInfos);
					convertFromStaffRaws(rsp!.sessions![0].staffAttributes!).forEach(value => {
						Weila_MemDB.getInstance().putStaff(value);
					})
					Weila_MemDB.getInstance().putService(serviceSessionInfo.service);
					return serviceSessionInfo;
				}

				return undefined;
			}catch (e) {
				return Promise.reject("获取服务会话失败" + e);
			}
		}

		return Promise.reject(new Error("build msg error"));
	}

	public async initService(dbSessionList: WL_IDbSession[]): Promise<boolean> {
		let serviceSessionInfos = [] as WL_IDbServiceSessionInfo[];
		if (dbSessionList.length == 0) {
			return true;
		}

		dbSessionList = dbSessionList.filter(value => {
			return value.sessionType == WL_IDbSessionType.SESSION_SERVICE_TYPE;
		});

		const sessionIds_long = dbSessionList.map(value => {
			return Long.fromValue(value.sessionId);
		});

		const buildMsgRet = WeilaPbBusinessWrapper.buildCommonGetSessionsReq(sessionIds_long);
		if (buildMsgRet.resultCode == 0) {
			try {
				const rsp = await this.coreInterface.sendPbMsg(buildMsgRet) as WL.Business.IRspCommonGetSessions;
				const services = [] as WL_IDbService[];
				let dbUserInfos = [] as WL_IDbUserInfo[];
				let allStaffs = [] as WL_IDbServiceStaff[];

				BLog("buildCommonGetSessionsReq %o", rsp)
				const validServiceSessionIds = rsp!.sessions!.map(value => {
					return new Long(value!.customerAttribute!.userInfo!.userId!, value!.serviceAttribute!.id!).toString(10);
				});

				for (let dbSession of dbSessionList) {
					const idx = validServiceSessionIds.indexOf(dbSession.sessionId);
					if (idx !== -1) {
						const serviceSessionRaw = rsp!.sessions![idx];
						const serviceSessionInfo = convertFromServiceSessionRaw(serviceSessionRaw);
						services.push(serviceSessionInfo.service);
						allStaffs.push(...serviceSessionInfo.staffs.map(value => {
							return value.staff;
						}));
						dbUserInfos.push(...serviceSessionInfo.staffs.map(value => {
							return value.userData;
						}));
						dbUserInfos.push(serviceSessionInfo.customer!);
						serviceSessionInfos.push(serviceSessionInfo);

						dbSession.latestUpdate = serviceSessionInfo.serviceSession.updatedTime;
						dbSession.sessionName = serviceSessionInfo.service.name;
						dbSession.sessionAvatar = serviceSessionInfo.service.avatar;
						dbSession.extra = serviceSessionInfo.serviceSession;
					} else {
						dbSession.status = WL_IDbSessionStatus.SESSION_INVALID;
						(dbSession.extra as WL_IDbServiceSession).serviceStatus = WL_ServiceStatus.SERVICE_STATUS_FINISH;
					}
				}

				dbUserInfos = dbUserInfos.filter((value, index, array) => {
					return array.findIndex(value1 => {
						return value1.userId == value.userId;
					}) == index;
				});

				Weila_MemDB.getInstance().putUsers(dbUserInfos);

				allStaffs = allStaffs.filter(((value, index, array) => {
					return array.findIndex(value1 => {
						return value1.userId == value.userId;
					}) == index;
				}));

				allStaffs.forEach(value => {
					Weila_MemDB.getInstance().putStaff(value);
				})

				services.forEach(value => {
					Weila_MemDB.getInstance().putService(value);
				})

				dbSessionList.forEach(value => {
					Weila_MemDB.getInstance().putSession(value);
				})

				return true;
			}catch (e) {
				return Promise.reject("获取服务会话失败" + e);
			}
		}

		return Promise.reject(new Error('创建消息出错'));
	}

	public async closeServiceSession(sessionId: string): Promise<boolean> {
		const buildRet = WeilaPbBusinessWrapper.buildCustomerCloseSessionReq(Long.fromValue(sessionId));
		if (buildRet.resultCode == 0) {
			await this.coreInterface.sendPbMsg(buildRet);
			return true;
		}

		return Promise.reject(new Error('创建消息出错'));
	}
}
